package com.siro.auth.utils.file;

import com.siro.auth.base.constant.Constants;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.DigestUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * 文件处理工具类
 *
 * @author starsea
 * @date 2022-11-12 15:07
 */
public class FileUtils {

    public static Logger log = LoggerFactory.getLogger(FileUtils.class);

    public static boolean checkAllowDownload(String resource) {
        //禁止目录上跳级别
        if (resource.contains("..")) {
            return false;
        }
        //检查允许下载的文件规则
        if (ArrayUtils.contains(Constants.DEFAULT_ALLOWED_EXTENSION, FileUtils.getFileType(resource))) {
            return true;
        }

        return false;
    }

    /**
     * 获取文件类型
     *
     * @param fileName
     * @return
     */
    private static Object getFileType(String fileName) {
        int separetorIndex = fileName.lastIndexOf(".");
        if (separetorIndex < 0) {
            return "";
        }
        return fileName.substring(separetorIndex + 1).toLowerCase();
    }

    /**
     * 下载文件名重新编码
     *
     * @param response
     * @param realFileName
     * @throws Exception
     */
    public static void setAttachementResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
        String pecentEncodeFileName = pecentEncode(realFileName);
        StringBuilder content = new StringBuilder();
        content.append("attachment;fileName=")
                .append(pecentEncodeFileName)
                .append(";")
                .append("fileName*=")
                .append("utf-8''")
                .append(pecentEncodeFileName);
        response.addHeader("Access-Control-Expose-Header", "Content-Disposition,download-fileName");
        response.addHeader("Content-disposition", content.toString());
        response.addHeader("download-fileName", pecentEncodeFileName);
    }

    /**
     * 百分百编码工具方法
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    private static String pecentEncode(String str) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(str, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "/%20");
    }

    /**
     * 输出指定文件的byte数组
     *
     * @param filePath     文件路径
     * @param outputStream 输出流
     * @throws IOException
     */
    public static void writeBytes(String filePath, ServletOutputStream outputStream) throws IOException {
        FileInputStream fis = null;
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = fis.read(b)) > 0) {
                outputStream.write(b, 0, len);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            IOUtils.close(outputStream);
            IOUtils.close(fis);
        }
    }

    /**
     * 输出指定文件的byte数组
     *
     * @param inputStream  输入流
     * @param outputStream 输出流
     * @throws IOException
     */
    public static void writeBytes(InputStream inputStream, ServletOutputStream outputStream) throws IOException {
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }

    }

    /**
     * 获取文件md5
     *
     * @param ins
     * @return
     */
    public static String getFileMD5String(InputStream ins) {
        String md5Result = StringUtils.EMPTY;
        try {
            byte[] bs = new byte[ins.available()];
            while (ins.read(bs) > 0) {
                md5Result = DigestUtils.md5DigestAsHex(bs);
            }
        } catch (Exception e) {
            log.error("文件获取md5值失败，错误信息{}", e.getMessage());
        }
        return md5Result;
    }
}
